package cn.net.mugui.web.tomcat;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.http.*;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;

import com.mugui.base.base.Autowired;
import com.mugui.base.base.Component;
import com.mugui.base.client.net.baghandle.NetHandle;
import com.mugui.base.client.net.bean.Message;
import com.mugui.base.client.net.bean.NetBag;

@Component
public class WebHandle extends HttpServlet {

	/**
	 *
	 */
	private static final long serialVersionUID = -5415248451131432324L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		handle(req, resp);
	}

	private void handle(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		req.setCharacterEncoding("UTF-8");
		resp.setCharacterEncoding("UTF-8");
		resp.setContentType("text/html;charset=UTF-8");
		handleCors(req, resp);


		AsyncContext startAsync = req.startAsync();
		startAsync.setTimeout(30000);
		startAsync.start(new Runnable() {
			@Override
			public void run() {
				PrintWriter outputStream = null;
				String bag = null;
				try {
					outputStream = resp.getWriter();
					bag = requestHandle(req, resp, req.getSession());
					outputStream.println(bag);
					outputStream.flush();
					outputStream.close();
				} catch (Exception e) {
					e.printStackTrace();
					if (outputStream != null) {
						outputStream.println(e.getMessage());
						outputStream.flush();
						outputStream.close();
					}
				} finally {
					if (outputStream != null) {
						outputStream.close();
					}
					startAsync.complete();
				}
			}
		});
	}


	/**
	 * 是否支持跨域
	 */
	@Setter
	@Getter
	private boolean isCors = false;


	private void handleCors(HttpServletRequest req, HttpServletResponse resp) {
		if (isCors) {
			//设置跨越支持
			resp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
			resp.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
			resp.setHeader("Access-Control-Max-Age", "3600");
			resp.setHeader("Access-Control-Allow-Headers", req.getHeader("Access-Control-Request-Headers"));
			resp.setHeader("Access-Control-Allow-Credentials", "true");
			resp.setStatus(HttpServletResponse.SC_OK);
		}
	}

	@Autowired
	private NetHandle netHandle;
	private static int bag_max = 1024 * 1024 * 10;

	private static ThreadLocal<Part> threadFile = new ThreadLocal<Part>();

	public static Part getFile() {
		return threadFile.get();
	}

	private String requestHandle(HttpServletRequest req, HttpServletResponse resp, HttpSession session)
			throws Exception {
		NetBag bag = new NetBag();
		bag.setType(NetBag.TYPE_HTTP);
		bag.setCode(200);
		bag.setFrom_host(req.getRemoteHost());
		bag.setFrom_port(req.getRemotePort());
		bag.setHost(req.getServerName());
		bag.setPort(req.getServerPort());
		bag.setTimestamp(System.currentTimeMillis() + "");
		String header = req.getHeader("Content-Type");
		if (StrUtil.contains(header,"multipart/form-data")) {
			Part file = req.getPart("file");
			if (file != null) {
				Part data = req.getPart("data");
				String read = IoUtil.read(data.getInputStream(), Charset.forName("utf-8"));
				NetBag temp = NetBag.newBean(NetBag.class, read);
				if (temp == null) {
					bag.setData(Message.error("参数错误"));
					bag.setRet_data(null);
					bag.setHost(null);
					bag.setPort(null);
					bag.setFrom_host(null);
					bag.setFrom_port(null);
					bag.setTimestamp(null).setServer_type(null);
					return bag.toString();
				}
				bag.InitBean(temp.get());
				bag.get().putAll(temp.get());
				threadFile.set(file);

			}
		} else if (req.getParameter("func") != null) {
			bag.setFunc(req.getParameter("func"));
			bag.setData(req.getParameter("data"));
			bag.setHash(req.getParameter("hash"));
			bag.setSession(req.getParameter("session"));
			bag.setServer_type(req.getParameter("server_type"));
			Map<String, String[]> parameterMap = req.getParameterMap();
			Iterator<Entry<String, String[]>> iterator = parameterMap.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<String, String[]> next = iterator.next();
				if (next.getValue() != null && next.getValue().length > 0)
					bag.get().put(next.getKey(), next.getValue()[0]);
			}
		} else {
			InputStream inputStream = req.getInputStream();
			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
			byte[] bs = new byte[1024];
			int len = 0;
			int max_len = 0;
			while ((len = inputStream.read(bs)) > -1) {
				outputStream.write(bs, 0, len);
				max_len += len;
				if (max_len > bag_max) {
					outputStream.close();
					inputStream.close();
					bag.setData(Message.error("limit " + bag_max));
					bag.setRet_data(null);
					bag.setHost(null);
					bag.setPort(null);
					bag.setFrom_host(null);
					bag.setFrom_port(null);
					bag.setTimestamp(null).setServer_type(null);
					return bag.toString();
				}
			}
			String body = outputStream.toString("UTF-8");

			outputStream.close();
			inputStream.close();
			if (StringUtils.isBlank(body)) {
				bag.setData(Message.error("参数错误"));
				bag.setRet_data(null);
				bag.setHost(null);
				bag.setPort(null);
				bag.setFrom_host(null);
				bag.setFrom_port(null);
				bag.setTimestamp(null).setServer_type(null);
				return bag.toString();
			}
			NetBag temp = NetBag.newBean(NetBag.class, body);
			if (temp == null) {
				bag.setData(Message.error("参数错误"));

				bag.setRet_data(null);
				bag.setHost(null);
				bag.setPort(null);
				bag.setFrom_host(null);
				bag.setFrom_port(null);
				bag.setTimestamp(null).setServer_type(null);
				return bag.toString();
			}
			bag.InitBean(temp.get());
			bag.get().putAll(temp.get());
		}
		if (!session.getId().equals(bag.getSession())) {
			SessionContext.DelSession(SessionContext.getSession(bag.getSession()));
		}
		SessionContext.AddSession(req.getSession());
		bag.setSession(session.getId());
		String tempbag = netHandle.httpHandle(bag, null);
		threadFile.set(null);
		return tempbag;
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		handle(req, resp);
	}

	@Override
	protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		handleCors(req, resp);
		resp.getWriter().println("ok");
	}
}
